#1) Loads constrained send and receive events
#2) Determines the paths for all these events
#  2a) Start condition, the node where the packet origninates changes the send event to "transmission" events
#  2b) Loop, a node either receives from a sent or forwards a received "transmission" event
#3) Also puts in one example to show how two evetns 
#   can be created when processing just for illustration purposes

# Evaluation criteria:
# a) implementability of the language construct?
#    assumption: eventset methods or slightly rewritten versions are available for the dSL
# b) optimization handling of fixed point operator
#    (the fpp can use predicates for filerting: 
#     by partitioning into distinct sets, the number of iterations
#     needed for searching matches can be reduced drastically)
# c) looks

Type :senddone do
 with :name=>:nodeid,:fieldtype=> :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79],:notification => :error
 with :name=>:destination, :fieldtype => :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79], :notification => :warning
 with :name=>:origin, :fieldtype => :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79],:notification => :error
 with :name=>:seqNo, :fieldtype=> :periodic, :range => 0..255, :notification => :error
 with :name=>:time, :fieldtype => :integer, :notification => :warning
end


Type :receive do
 with :name=>:nodeid,:fieldtype=> :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79],:notification => :error
 with :name=>:destination, :fieldtype => :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79], :notification => :warning
 with :name=>:origin, :fieldtype => :integer, :range => [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79],:notification => :error
 with :name=>:seqNo, :fieldtype=> :periodic, :range => 0..255, :notification => :error
 with :name=>:time, :fieldtype => :integer, :notification => :warning
end

all = loadlog(path + '/small.log')

# a)  Fluent interfaces-> satisfy-method takes the predicate function and returns self. 
#     merge-method is called on self which calls transform, which uses its name as a parameter
#     blocks are the same as for the current methods
#     iterative is the same as for the eventset
# => General issue: how to count how many parameters you have in a block?
# b) how to parse this general predicate, we can optmize if we partition for origin and for sequence number
# c) 
#      + Hash notation for events is good
#      0 Explicit addressing of eventsets
#      - The long predicates are not nice, since you have to use line breakers to make it readable
#      - Multi event return is an array "[]" is not intuitive
#      - when creating a processed evenet some defaults would be maybe nice to minimize writing effort

#Start Condition
routestart = all.satisfy{|send| send[:origin] == send[:nodeid] and send[:name] == :senddone}.merge do |send, receive|
      {
       :origin => send[:origin],
       :nodeid => send[:nodeid],
       :seqNo   => send[:seqNo],
       :type   => :route
     }
    end

#Route Processing
routes = routestart.iterative do |iteration|
  iteration.satisfy{|send, receive| send[:origin] == receive[:origin] and send[:seqNo] == receive[:seqNo] and \
    ((send[:dest] = receive[:nodeid] and send[:type] == :route and receive[:type] == :receive) or \
     (send[:nodeid] = receive[:nodeid] and send[:type] == :senddone and receive[:type] == :route))}.merge do |send, receive|
      {
       :origin => send[:origin],
       :nodeid   => receive[:nodeid],
       :seqNo   => send[:seqNo],
       :type   => :route
     }
    end
  end
  
#Multiple event example - switch some information
processed = all.satisfy{|send, receive| send[:origin] == receive[:origin] and send[:dest] = receive[:nodeid] and send[:seqNo] == receive[:seqNo]}.merge do |send, receive|
      [
      {
       :type => :send_success,
       :origin => send[:origin],
       :nodeid   => send[:nodeid],
       :seqNo   => send[:seqNo]       
     },
     {
       :type => :receive_success,
       :origin => receive[:origin],
       :nodeid   => receive[:nodeid],
       :seqNo   => send[:seqNo]
     }
    ]
    end